package com.coco.goods.service.impl;

import com.coco.common.result.ResultData;
import com.coco.goods.mapper.CategoryMapper;
import com.coco.goods.pojo.TbCategory;
import com.coco.goods.service.CategoryService;
import com.coco.goods.vo.CategorySearchVo;
import com.coco.goods.vo.CategoryTreeVo;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Package: com.coco.goods.service.impl
 * @Author: minicoco
 * @Date: Created in 2021/7/15 上午 10:46
 */
@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {


    @Autowired(required = false)
    private CategoryMapper categoryMapper;

    private RedisTemplate redisTemplate;

    @Autowired(required = false)
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        //Json 序列化配置
        Jackson2JsonRedisSerializer objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectJackson2JsonRedisSerializer.setObjectMapper(om);

        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(objectJackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(objectJackson2JsonRedisSerializer);
        this.redisTemplate = redisTemplate;
    }

    @Override
    public List<TbCategory> linkage(Long id) {
        return categoryMapper.linkage(id);
    }

    /**
     * 获取三级菜单（有空属性）
     *
     * @return java.util.List<com.coco.goods.vo.CategoryTreeVo>
     * @author HanSama
     * @date 2021/7/15 19:48
     */
    @Override
    public List<CategoryTreeVo> getCategoryTree() {

        List<TbCategory> all = categoryMapper.findAll();

        List<CategoryTreeVo> levelOne = all.stream().filter(category ->
                //获取顶级菜单
                category.getParentId().longValue() == 0
        ).map((menu) -> {
            CategoryTreeVo treeVo = new CategoryTreeVo();
            treeVo.setValue(menu.getId());
            treeVo.setLabel(menu.getName());
            //查找子菜单
            treeVo.setChildren(getChildrens(menu, all));
            return treeVo;
        }).collect(Collectors.toList());

        return levelOne;
    }


    /**
     * 获取当前菜单的子菜单
     *
     * @param root
     * @param all
     * @return java.util.List<com.coco.goods.vo.CategoryTreeVo>
     * @author HanSama
     * @date 2021/7/15 19:49
     */
    private List<CategoryTreeVo> getChildrens(TbCategory root, List<TbCategory> all) {

        List<CategoryTreeVo> collect = all.stream().filter(category ->
                category.getParentId().longValue() == root.getId().longValue()
        ).map((menu) -> {

            CategoryTreeVo treeVo = new CategoryTreeVo();
            treeVo.setValue(menu.getId());
            treeVo.setLabel(menu.getName());
            List<CategoryTreeVo> childrens = getChildrens(menu, all);
            if (childrens == null) {
                treeVo.setChildren(null);
            } else {
                treeVo.setChildren(childrens);
            }
            return treeVo;
        }).collect(Collectors.toList());
        return collect;
    }


    /**
     * 获取三级菜单（无空属性）
     *
     * @return java.util.List<java.util.Map>
     * @author HanSama
     * @date 2021/7/15 20:53
     */
    @Override
    public List<Map> findTree() {
        List<Map> findTree = (List<Map>) redisTemplate.opsForValue().get("findTree");

        if (findTree!=null){
            log.info("从Redis获取 级联");
         return findTree;
        }

        List<TbCategory> all = categoryMapper.findAll();

        ArrayList<Map> maps = new ArrayList<>();
        log.info("从MySQL获取 级联");
        for (TbCategory entity : all) {

            if (entity.getParentId().longValue() == 0) {
                HashMap<String, Object> map = new HashMap<>(64);
                map.put("value", entity.getId());
                map.put("label", entity.getName());
                map.put("children", findChildrens(entity, all));
                maps.add(map);
            }

        }
        redisTemplate.opsForValue().set("findTree",maps);

        return maps;
    }

    /**
     * 获取当前菜单的子菜单（无空属性）
     *
     * @param entity
     * @param all
     * @return java.util.List<java.util.Map>
     * @author HanSama
     * @date 2021/7/15 20:53
     */
    private List<Map> findChildrens(TbCategory entity, List<TbCategory> all) {

        ArrayList<Map> list = new ArrayList<>();
        for (TbCategory cate : all) {

            if (cate.getParentId().longValue() == entity.getId().longValue()) {
                HashMap<String, Object> map = new HashMap<>(64);
                map.put("value", cate.getId());
                map.put("label", cate.getName());
                List<Map> childrens = findChildrens(cate, all);
                if (childrens != null && childrens.size() > 0) {
                    map.put("children", childrens);
                }
                list.add(map);
            }

        }
        return list;
    }


    @Override
    public List<Map> searchCategory(CategorySearchVo searchVo) {

        List<Map> mapList = (List<Map>) redisTemplate.opsForValue().get("searchCategory");

        if (mapList!=null){
            log.info("从Redis获取 三级列表");
            return mapList;
        }

        List<TbCategory> all = categoryMapper.searchCategory(searchVo);
        ArrayList<Map> maps = new ArrayList<>();

        log.info("从MySQL获取 三级列表");

        for (TbCategory entity : all) {

            if (entity.getParentId().longValue() == 0) {
                HashMap<String, Object> map = new HashMap<>(64);
                //基础属性
                map.put("id", entity.getId());
                map.put("name", entity.getName());
                map.put("parentId", entity.getParentId());
                map.put("imgUrl", entity.getImgUrl());
                map.put("orderCloum", entity.getOrderCloum());
                map.put("status", entity.getStatus());
                map.put("children", findChildren(entity, all));
                maps.add(map);
            }
        }

        redisTemplate.opsForValue().set("searchCategory",maps);
        return maps;
    }


    @Override
    public void deleteById(Long id) {
        categoryMapper.deleteById(id);
    }

    private List<Map> findChildren(TbCategory entity, List<TbCategory> all) {
        ArrayList<Map> list = new ArrayList<>();
        for (TbCategory cate : all) {
            if (cate.getParentId().longValue() == entity.getId().longValue()) {
                HashMap<String, Object> map = new HashMap<>(64);
                map.put("id", cate.getId());
                map.put("name", cate.getName());
                map.put("parentId", cate.getParentId());
                map.put("imgUrl", cate.getImgUrl());
                map.put("orderCloum", cate.getOrderCloum());
                map.put("status", cate.getStatus());

                List<Map> children = findChildren(cate, all);
                if (children != null && children.size() > 0) {
                    map.put("children", children);
                }
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 查询所有
     *
     * @return
     * @author hu
     * @date 2021/7/16 09:13
     */
    @Override
    public List<TbCategory> findAll() {
        List<TbCategory> list = categoryMapper.findAll();
        list.forEach(li -> {
            li.setOneName(categoryMapper.findName(li.getParentId()));
        });
        return list;
    }

    /**
     * 查询单条分类数据
     *
     * @param id
     * @return
     * @author hu
     * @date 2021/7/16 09:13
     */
    @Override
    public TbCategory findOne(Long id) {
        return categoryMapper.findOne(id);
    }

    /**
     * 添加分类数据
     *
     * @param category
     * @return
     * @author hu
     * @date 2021/7/16 09:13
     */
    @Override
    public void addCategory(TbCategory category) {
        redisTemplate.delete("findTree");
        redisTemplate.delete("searchCategory");
        categoryMapper.addCategory(category);
    }

    /**
     * 分页加查询
     *
     * @param categorySearchVo
     * @return
     * @author hu
     * @date 2021/7/16 09:13
     */
    @Override
    public ResultData findAllSearch(CategorySearchVo categorySearchVo) {
        PageHelper.startPage(categorySearchVo.getPage(), categorySearchVo.getLimit());
        List<TbCategory> categoryList = categoryMapper.selectByExample(categorySearchVo);
        PageInfo<TbCategory> pageInfo = new PageInfo<>(categoryList);
        return new ResultData(pageInfo.getList(), pageInfo.getTotal());
    }


    /**
     * 修改分类数据
     *
     * @param category
     * @return
     * @author hu
     * @date 2021/7/16 09:13
     */
    @Override
    public void update(TbCategory category) {
        redisTemplate.delete("findTree");
        redisTemplate.delete("searchCategory");
        categoryMapper.update(category);
    }

    /**
     * 修改状态 0显示  1隐藏
     *
     * @param
     * @return
     * @author hu
     * @date 2021/7/16 09:13
     */
    @Override
    public void updStatus(Long id, Integer status) {
        redisTemplate.delete("findTree");
        redisTemplate.delete("searchCategory");
        if (id != null || status != null) {

            categoryMapper.updStatus(id, status);

        }

    }


}
